<?php

namespace App\Service\WorkOrder\Mission;

use App\Enums\BaseErrorCode;
use App\Enums\WorkOrder\ErrCode;
use App\Enums\WorkOrder\MissionEnum;
use App\Enums\WorkOrder\OrderEnum;
use App\Exceptions\Custom\CustomHttpResponseException;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\Rms\RmsUserApi;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\WorkOrder\WorkOrderApplyMainModel;
use App\Models\WorkOrder\WorkOrderApplyManagerModel;
use App\Models\WorkOrder\WorkOrderMissionModel;
use App\Models\WorkOrder\WorkOrderOperateLogModel;
use App\Models\WorkOrder\WorkOrderRejectModel;
use App\Models\WorkOrder\WorkOrderUserRoleModel;
use App\Service\OpenShop\User\RmsUserService;
use App\Service\WorkOrder\FunctionOpen\FunctionOpenService;
use App\Service\WorkOrder\Manager\ManagerService;
use App\Service\WorkOrder\Message\SendFsService;
use App\Service\WorkOrder\Message\SendSmsService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class MissionEngineService
{
    private WorkOrderApplyMainModel $applyMainModel;

    /**
     * @param string|WorkOrderApplyMainModel $workOrderNo
     */
    public function __construct($workOrderNo)
    {
        if ($workOrderNo instanceof WorkOrderApplyMainModel) {
            $this->applyMainModel = $workOrderNo;
        } else {
            $this->applyMainModel = WorkOrderApplyMainModel::query()->where('workOrderNo', $workOrderNo)->first();
        }
    }

    /**
     * 工单的全流程
     * @return array
     */
    public function progress(): array
    {
        $lists = [];

        switch ($this->applyMainModel->problemPid) {
            case OrderEnum::PROBLEM_PID_4:
            case OrderEnum::PROBLEM_PID_6:
            case OrderEnum::PROBLEM_PID_7:
            case OrderEnum::PROBLEM_PID_8:
            case OrderEnum::PROBLEM_PID_9:
            case OrderEnum::PROBLEM_PID_10:
                $lists = [MissionEnum::STEP_1, MissionEnum::STEP_2, MissionEnum::STEP_4, MissionEnum::STEP_99];
                break;
            case OrderEnum::PROBLEM_PID_1:
            case OrderEnum::PROBLEM_PID_2:
                $lists = [
                    MissionEnum::STEP_1,
                    MissionEnum::STEP_2,
                    MissionEnum::STEP_3,
                    MissionEnum::STEP_4,
                    MissionEnum::STEP_99
                ];
                break;
            case OrderEnum::PROBLEM_PID_5:
                if (in_array($this->applyMainModel->problemChildId, [
                    OrderEnum::PROBLEM_PID_5_CHILDREN_101,
                    OrderEnum::PROBLEM_PID_5_CHILDREN_102
                ])) {
                    $lists = [
                        MissionEnum::STEP_1,
//                        MissionEnum::STEP_6,
                        MissionEnum::STEP_2,
                        MissionEnum::STEP_4,
                        MissionEnum::STEP_5,
                        MissionEnum::STEP_99
                    ];
                } elseif ($this->applyMainModel->problemChildId == OrderEnum::PROBLEM_PID_5_CHILDREN_105) {
                    $lists = [MissionEnum::STEP_1, MissionEnum::STEP_7, MissionEnum::STEP_8, MissionEnum::STEP_99];
                } else {
                    $lists = [MissionEnum::STEP_1, MissionEnum::STEP_4, MissionEnum::STEP_99];
                }
                break;
        }

        return $lists;
    }

    /**
     * web端显示的流程进度
     * @return array
     */
    public function webShowProgress(): array
    {
        return collect($this->progress())
            ->filter(function ($step) {
                return $step != MissionEnum::STEP_3;
            })
            ->values()
            ->toArray();
    }

    public function getNextStep()
    {
        $lists = $this->progress();
        foreach ($lists as $k => $step) {
            if ($step == $this->applyMainModel->step) {
                return $lists[$k + 1] ?? -1;
            }
        }

        return -1;
    }

    /**
     * 完成任务
     * @return void
     */
    public function finish(int $nowStep)
    {
        // 幂等、防止重复finish跳步骤
        if ($nowStep != $this->applyMainModel->step) {
            Log::warning("MissionEngineService.finish step diff: {$this->applyMainModel->workOrderNo}", [
                "paramStep" => $nowStep,
                "dbStep"    => $this->applyMainModel->step,
            ]);

            throw new CustomHttpResponseException(ErrCode::errCodeTrans(ErrCode::CODE_ERR_ENGINE_FINISH_REPEAT));
        }

        // 下阶段任务
        $nextStep = $this->getNextStep();
        if ($nextStep == -1) {
            throw new CustomHttpResponseException(ErrCode::errCodeTrans(ErrCode::CODE_ERR_NEXT_STEP_ERR));
        }


        // 新增任务前校验
        $nextStepMission = WorkOrderMissionModel::query()
                                                ->where('workOrderNo', $this->applyMainModel->workOrderNo)
                                                ->where('step', $nextStep)
                                                ->count();

        if ($nextStepMission) {
            throw new CustomHttpResponseException(ErrCode::errCodeTrans(ErrCode::CODE_ERR_NEXT_STEP_MISSION_EXISTS));
        }

        // 完成任务
        if ($this->applyMainModel->step != MissionEnum::STEP_1) {
            WorkOrderMissionModel::finish($this->applyMainModel->workOrderNo, $this->applyMainModel->step);
        }

        // 阶段变更
        WorkOrderApplyMainModel::saveStep($this->applyMainModel->workOrderNo, $nextStep);

        //功能开通附加钩子
        FunctionOpenService::hook($this->applyMainModel, $nextStep);

        // 当前阶段
        switch ($this->applyMainModel->step) {

            // 新建订单
            case MissionEnum::STEP_1:
                switch ($this->applyMainModel->problemPid) {
                    case OrderEnum::PROBLEM_PID_5:
                        // 功能开通 - 直接到产品负责人处理
                        if ($this->applyMainModel->isFunctionWaiMaiOpen()) {
                            $role = WorkOrderUserRoleModel::ROLE_TYPE_6;
                            // 抢单类型处理，给所有负责人推消息
                            $feishuIds = WorkOrderUserRoleModel::query()->where('role', $role)->pluck('feishuId')
                                                               ->toArray();
                            $feishuIds = array_unique($feishuIds);
                            (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeProcessorOptimize($role,
                                $feishuIds);
                        } else {
                            $role    = WorkOrderUserRoleModel::ROLE_TYPE_4;
                            $dealUid = ManagerService::popManagerId(
                                $role, $this->applyMainModel->problemPid,
                                $this->applyMainModel->problemChildId, 0, $this->applyMainModel->shopId
                            );
                            WorkOrderApplyManagerModel::add($this->applyMainModel->workOrderNo, $role, $dealUid);
                            WorkOrderMissionModel::add($this->applyMainModel->workOrderNo, $nextStep, $dealUid);
                            WorkOrderApplyMainModel::saveStep($this->applyMainModel->workOrderNo, $nextStep);
                            (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeProcessor($role);
                        }
                        break;
                    default:
                        // 问题反馈 - 客服审核
                        $role    = WorkOrderUserRoleModel::ROLE_TYPE_1;
                        // 抢单类型处理，给所有负责人推消息
                        WorkOrderApplyMainModel::saveStep($this->applyMainModel->workOrderNo, MissionEnum::STEP_3);
                        $feishuIds = WorkOrderUserRoleModel::query()->where('role', $role)->pluck('feishuId')
                            ->toArray();
                        (new SendFsService($this->applyMainModel->workOrderNo))->enableGrab($feishuIds);
                        /*$dealUid = ManagerService::popManagerId($role, 0, 0);
                        WorkOrderApplyManagerModel::add($this->applyMainModel->workOrderNo, $role, $dealUid);
                        WorkOrderMissionModel::add($this->applyMainModel->workOrderNo, $nextStep, $dealUid);
                        (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeProcessor($role)*/;
                }

                break;

            // 客服初审
            case MissionEnum::STEP_2:
                // 阶段变更
                WorkOrderApplyMainModel::saveStep($this->applyMainModel->workOrderNo, $nextStep);
                if ($this->applyMainModel->isFunctionWaiMaiOpen()) {
                    $role             = WorkOrderUserRoleModel::ROLE_TYPE_7;
                    $provinceCode     = (new SendFsService($this->applyMainModel->workOrderNo))->getShopProvinceCode();
                    $waimaiManageList = ManagerService::getAreaWaiMaiManagerUserId($provinceCode);
                    $dealUid          = current($waimaiManageList['userIds']);

                    WorkOrderApplyManagerModel::add($this->applyMainModel->workOrderNo, $role, $dealUid);
                    WorkOrderMissionModel::add($this->applyMainModel->workOrderNo, $nextStep, $dealUid);

                    // 客服、产品收到待处理工单
                    // 萨博等人收到消息
                    (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeWaimaiManage($role,
                        [$dealUid]);
                    // 通知群消息
                    (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeWaimaiManageGroup($waimaiManageList['sendFsRobotId']);
                    // 省总发消息
                    (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeWaimaiProvince();
                    // 全员发消息
//                    (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeWaimaiGroup();


                } else {

                    $role = OrderEnum::PROBLEM_PID_TO_ROLE[$this->applyMainModel->problemPid] ?? 0;
                    if (!$role) {
                        throw new CustomHttpResponseException(ErrCode::errCodeTrans(ErrCode::CODE_ERR_PROBLEM_PID_TO_ROLE));
                    }

                    // 仓配问题，负责人已经被指派
                    // 功能开通，负责人已经被指派
                    // 品控问题，负责人待抢单
                    if (!in_array($this->applyMainModel->problemPid, OrderEnum::GRAB_PIDS)) {

                        // 工单对应的负责人
                        $dealUids = WorkOrderApplyManagerModel::getMangerIdsByRole($this->applyMainModel->workOrderNo,
                            $role);

                        if (count($dealUids) == 0) {
                            throw new CustomHttpResponseException(ErrCode::errCodeTrans(ErrCode::CODE_ERR_MANAGER_ASSIGN));
                        }

                        foreach ($dealUids as $dealUid) {
                            WorkOrderMissionModel::add($this->applyMainModel->workOrderNo, $nextStep, $dealUid);

                            // 新增问题工单指派当前处理人
                            if (in_array($this->applyMainModel->problemPid, OrderEnum::NEW_GRAB_PIDS)) {
                                WorkOrderApplyManagerModel::add($this->applyMainModel->workOrderNo, $role, $dealUid);
                            }
                        }

                        $userIds = [];

                        (new SendFsService($this->applyMainModel->workOrderNo))->kfDistributeProcessor($role, $userIds);

                    } else {

                        // 抢单类型处理，给所有负责人推消息
                        $feishuIds = WorkOrderUserRoleModel::query()->where('role', $role)->pluck('feishuId')
                                                           ->toArray();
                        (new SendFsService($this->applyMainModel->workOrderNo))->enableGrab($feishuIds);
                    }
                }

                break;

            // 待抢单
            case MissionEnum::STEP_3:
                // 阶段变更
                WorkOrderApplyMainModel::saveStep($this->applyMainModel->workOrderNo, $nextStep);
                break;

            // 负责人处理
            case MissionEnum::STEP_4:
                // 阶段变更
                WorkOrderApplyMainModel::saveStep($this->applyMainModel->workOrderNo, $nextStep);

                if ($this->applyMainModel->isFunctionWaiMaiOpen()) {

                    // 功能开通 - 直接到产品负责人处理
                    $role    = WorkOrderUserRoleModel::ROLE_TYPE_4;
                    $dealUid = ManagerService::popManagerId($role, $this->applyMainModel->problemPid,
                        $this->applyMainModel->problemChildId);

                    WorkOrderApplyManagerModel::add($this->applyMainModel->workOrderNo, $role, $dealUid);
                    WorkOrderMissionModel::add($this->applyMainModel->workOrderNo, $nextStep, $dealUid);

                    (new SendFsService($this->applyMainModel->workOrderNo))->workOrderApplyResult(true);
                    (new SendFsService($this->applyMainModel->workOrderNo))->kfWaimaiFunctionOpenMessage($role,
                        [$dealUid], '外卖经理已审批');

                } else {
                    (new SendFsService($this->applyMainModel->workOrderNo))->workOrderApplyResult(true);
                    (new SendSmsService($this->applyMainModel->workOrderNo))->workOrderApplyResult(true);
                }


                break;
            // 外卖负责人流程处理
            case MissionEnum::STEP_5:

                WorkOrderApplyMainModel::saveStep($this->applyMainModel->workOrderNo, $nextStep);

                if ($this->applyMainModel->isFunctionWaiMaiOpen()) {
                    // 外卖部门推送消息
                    (new SendFsService($this->applyMainModel->workOrderNo))->kfWaimaiOpenFinalMessage();
                    // 省总推送消息
                    (new SendFsService($this->applyMainModel->workOrderNo))->kfWaimaiOpenFinalPraesesMessage();

                } else {
                    (new SendFsService($this->applyMainModel->workOrderNo))->workOrderApplyResult(true);
                    (new SendSmsService($this->applyMainModel->workOrderNo))->workOrderApplyResult(true);
                }


                break;
            default:

                // 报错
                break;

        }
    }

    /**
     * 是否可以转交任务
     * @param int $currentUid
     * @param bool $throw
     * @return bool
     */
    public function checkTransfer(int $currentUid, bool $throw = false): bool
    {

        // 功能开通-夸父收银进件2.0 工单转交不限制
        if ($this->applyMainModel->step != MissionEnum::STEP_4 &&
            !($this->applyMainModel->problemPid == OrderEnum::PROBLEM_PID_5 &&
                $this->applyMainModel->problemChildId == OrderEnum::PROBLEM_PID_5_CHILDREN_105 &&
                in_array($this->applyMainModel->step, [MissionEnum::STEP_1, MissionEnum::STEP_7, MissionEnum::STEP_8])
            )) {
            if ($throw) {
                throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "仅在业务处理阶段才能转交任务");
            } else {
                return false;
            }
        }

        $mission = WorkOrderMissionModel::query()
                                        ->where('workOrderNo', $this->applyMainModel->workOrderNo)
                                        ->where('dealUid', $currentUid)
                                        ->where('missionStatus', MissionEnum::MISSION_STATUS_0)
                                        ->first();
        if (!$mission) {
            if ($throw) {
                throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "您当前不是任务处理人，无法转交任务");
            } else {
                return false;
            }
        }

        return true;
    }

    /**
     * 任务转交
     * @param int $targetUid
     */
    public function transfer(int $currentUid, int $targetUid, bool $sendFs = true): void
    {
        // 校验
        $this->checkTransfer($currentUid, true);

        // 查询用户信息
        $userInfo = RmsUserService::getRmsUserInfoByUserIds([$targetUid])['data'][0] ?? [];
        if (!$userInfo) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "不存在的用户id");
        }

        if ($userInfo['status'] != RmsUserApi::USER_STATUS_OK) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "用户被禁用");
        }

        DB::beginTransaction();

        // applyManager
        $oriApplyManager            = WorkOrderApplyManagerModel::query()
                                                                ->where('workOrderNo',
                                                                    $this->applyMainModel->workOrderNo)
                                                                ->where('status', WorkOrderApplyManagerModel::STATUS_ON)
                                                                ->where('managerId', $currentUid)
                                                                ->orderByDesc('id')//最新一条工单负责人
                                                                ->first();
        $managerName = $oriApplyManager->managerName;
        $oriRole                    = $oriApplyManager->role;
        $oriApplyManager->isDeleted = 1;
        $oriApplyManager->save();

        WorkOrderApplyManagerModel::add($this->applyMainModel->workOrderNo, $oriRole, $targetUid,
            $userInfo['username']);

        // mission
        $mission = WorkOrderMissionModel::query()
                                        ->where('workOrderNo', $this->applyMainModel->workOrderNo)
                                        ->where('dealUid', $currentUid)
                                        ->where('missionStatus', MissionEnum::MISSION_STATUS_0)
                                        ->orderByDesc('id')//最新一条工单负责人
                                        ->first();

        WorkOrderMissionModel::add($this->applyMainModel->workOrderNo, $mission->step, $targetUid,
            MissionEnum::MISSION_STATUS_0);
        $mission->isDeleted = 1;
        $mission->save();

        // reject
        WorkOrderRejectModel::transfer($currentUid, $targetUid);

        //增加工单日志
        WorkOrderOperateLogModel::generateOperateLog(
            $this->applyMainModel->workOrderNo,
            $this->applyMainModel->step,
            WorkOrderOperateLogModel::TYPE_15,
            $managerName,
            $currentUid,
            vsprintf("工单转交 %s -> %s", [$managerName, $userInfo['username']])
        );

        DB::commit();

        if ($sendFs) {

            //给对应的人发送消息
            (new SendFsService($this->applyMainModel->workOrderNo))->transferWorkOrder([$userInfo['feishuUserId']]);
        }
    }
}
